#include "StdAfx.h"
#include "ThirdPersonCamera.h"
#include "ICameraImpl.h"
#include "RenderableObject.h"
#include "BoundingVolume.h"


///////////////////////////////////////////////////////////////////////////////

CThirdPersonCamera::CThirdPersonCamera(ICameraImpl& cameraImpl, 
                                       IMovable& avatar)
      : m_cameraImpl(cameraImpl),
      m_avatar(avatar),
      m_cameraOffset(0, 10, -20),
      m_cameraLag(0.1f)
{
   m_cameraImpl.setPosition(m_avatar.getPosition() + m_cameraOffset);
   m_cameraImpl.lookAt(m_avatar.getPosition());
}

///////////////////////////////////////////////////////////////////////////////

void CThirdPersonCamera::move(const D3DXVECTOR3& transVec)
{
   m_cameraImpl.setPosition(m_cameraImpl.getPosition() + transVec);
   m_cameraImpl.lookAt(m_avatar.getPosition());
}

///////////////////////////////////////////////////////////////////////////////

void CThirdPersonCamera::rotate(float pitch, float yaw, float roll)
{
   // do not rotate the camera when told to...
}

///////////////////////////////////////////////////////////////////////////////

void CThirdPersonCamera::update(float timeElapsed)
{
   if (m_cameraLag != 0.0f) timeElapsed = timeElapsed * (1.0f / m_cameraLag);

   // Build a rotation matrix so that we can rotate our offset vector to it's position behind the player
   D3DXMATRIX mtxRotate;
   D3DXMatrixIdentity(&mtxRotate);
   D3DXVECTOR3 vecRight = m_avatar.getRightVec();
   D3DXVECTOR3 vecUp = m_avatar.getUpVec();
   D3DXVECTOR3 vecLook = m_avatar.getLookVec();
   mtxRotate._11 = vecRight.x; mtxRotate._21 = vecUp.x; mtxRotate._31 = vecLook.x;
	mtxRotate._12 = vecRight.y; mtxRotate._22 = vecUp.y; mtxRotate._32 = vecLook.y;
	mtxRotate._13 = vecRight.z; mtxRotate._23 = vecUp.z; mtxRotate._33 = vecLook.z;

   // Calculate our rotated offset vector
   D3DXVECTOR3 vecOffset;
   D3DXVec3TransformCoord(&vecOffset, &m_cameraOffset, &mtxRotate);
    
   // vecOffset now contains information to calculate where our camera position SHOULD be.
   D3DXVECTOR3 vecPosition = m_avatar.getPosition() + vecOffset;
   D3DXVECTOR3 vecDir = vecPosition - m_cameraImpl.getPosition();
   float length = D3DXVec3Length(&vecDir);
   D3DXVec3Normalize(&vecDir, &vecDir);

   // Move based on camera lag
   float distance = length * timeElapsed;
   if (distance > length) distance = length;

   // If we only have a short way to travel, move all the way
   if (length < 0.01f) distance = length;
    
   // Update our camera
   if (distance > 0)
   {
      m_cameraImpl.setPosition(m_cameraImpl.getPosition() + vecDir * distance);
      m_cameraImpl.lookAt(m_avatar.getPosition());
   }
}

///////////////////////////////////////////////////////////////////////////////

AABoundingBox CThirdPersonCamera::getWorldSpaceBoundingBox() const
{
   AABoundingBox bbox = m_avatar.getWorldSpaceBoundingBox();
   
   bbox.min += m_cameraImpl.getPosition() - m_avatar.getPosition();
   bbox.max += m_cameraImpl.getPosition() - m_avatar.getPosition();

   return bbox;
}

///////////////////////////////////////////////////////////////////////////////

const D3DXVECTOR3& CThirdPersonCamera::getRightVec() const 
{
   return m_avatar.getRightVec();
}

///////////////////////////////////////////////////////////////////////////////

const D3DXVECTOR3& CThirdPersonCamera::getUpVec() const 
{
   return m_avatar.getUpVec();
}

///////////////////////////////////////////////////////////////////////////////

const D3DXVECTOR3& CThirdPersonCamera::getLookVec() const 
{
   return m_avatar.getLookVec();
}

///////////////////////////////////////////////////////////////////////////////

const D3DXVECTOR3& CThirdPersonCamera::getPosition() const 
{
   return m_cameraImpl.getPosition();
}

///////////////////////////////////////////////////////////////////////////////

